home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / fdimg / —‹Œêsrc.lzh / line.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  24KB  |  1,132 lines

  1. #include    "3DDEF.H"
  2. #include    "GLOBAL.H"
  3. #include    "FORWARD.H"
  4. #include    "XCODE.H"
  5.  
  6. /* 行管理 */
  7.  
  8. /* カレントウインドウの最上行を得る */
  9. UNIT *
  10. line_my_top()
  11. {
  12.     register UNIT *p;
  13.  
  14.     p = SCREEN[CWY0];
  15.     if ((int)p & (int)0xffffff00) {
  16.         return(p);
  17.     }
  18.     return(SCREEN[CWY0]);
  19. }
  20.  
  21. /* カレントウインドウの n 行目を得る */
  22. UNIT *
  23. line_my_screen(int n)
  24. {
  25.     return(SCREEN[CWY0 + n]);
  26. }
  27.  
  28. /* w 番ウインドウの n 行目を得る */
  29. UNIT *
  30. line_x_screen(int w,int n)
  31. {
  32.     return(SCREEN[WDATA[w].WY0 + n]);
  33. }
  34.  
  35. /* up の begin_byte から、tb バイトだけたどる */
  36. /* 新しい行へのポインタを返す */
  37. /* new_byte_count にその行の何バイト目なのかを返す */
  38. /* movel != NIL なら、*movel に、実際に移動した行数(+-)を返す */
  39. UNIT *
  40. line_trace_byte(UNIT *up, int begin_byte, int tb, int *new_byte_count, int *movel)
  41. {
  42.     register UNIT *wp;
  43.     register int len,counter = 0;
  44.  
  45.     tb += begin_byte;
  46.     wp = up;
  47.  
  48.     line_seigyou();
  49.     if (tb >= 0) {    /* 後ろへトレース */
  50.         while(1) {
  51.             len = (wp->LENGTH);
  52.             if (len >= tb) {
  53.                 *new_byte_count = tb;
  54.                 break;
  55.             }
  56.             tb -= len;
  57. #if 0
  58. if (!(wp->ATO)) {
  59.     wp->ATO = TAIL;
  60.     *new_byte_count = wp->LENGTH;    /* 最後の行の右端 */
  61.     break;
  62. }
  63. #endif
  64.             if ((wp = wp->ATO) == TAIL) {
  65.                 wp = TAIL->MAE;
  66.                 *new_byte_count = wp->LENGTH;    /* 最後の行の右端 */
  67.                 break;
  68.             }
  69.             counter++;
  70.         }
  71.     } else {    /* 前へトレース */
  72.         tb = -tb;
  73.         while(1) {
  74.             len = wp->LENGTH;
  75.             if (len >= tb) {
  76.                 *new_byte_count = len - tb;
  77.                 break;
  78.             }
  79.             tb -= len;
  80.             if ((wp = wp->MAE) == HEAD) {
  81.                 wp = HEAD->ATO;
  82.                 *new_byte_count = 0;    /* 最初の行の左端 */
  83.                 break;
  84.             }
  85.             counter--;
  86.         }
  87.     }
  88.     if (movel) {
  89.         *movel = counter;
  90.     }
  91.     return(wp);
  92. }
  93.  
  94. /* up から tl 行たどる */
  95. /* 頭もしくは尾に達したら 頭行もしくは尾行を返す */
  96. /* movel != NIL なら、*movel に、実際に移動した行数(+-)を返す */
  97. UNIT *
  98. line_trace(UNIT *up, int tl, int *movel)
  99. {
  100.     register UNIT *wp;
  101.     register int i,counter=0;
  102.  
  103.     wp = up;
  104.  
  105.     if (tl) {    /* tl が0でないなら */
  106.         if (tl > 0) {
  107.             for(i=0;i<tl;i++,counter++) {
  108.                 if (wp == NULL) {
  109.                     break;
  110.                 }
  111.                 if ((wp = wp->ATO) == TAIL) {
  112.                     wp = TAIL->MAE;    /* 戻る */
  113.                     break;
  114.                 }
  115.                 if (wp->ATO == NULL) {
  116.                     wp = wp->MAE;
  117.                     counter--;
  118.                     break;
  119.                 }
  120.             }
  121.         } else {
  122.             tl = -tl;
  123.             for(i=0;i<tl;i++,counter--) {
  124.                 if (wp == NULL) {
  125.                     break;
  126.                 }
  127.                 if ((wp = wp->MAE) == HEAD) {
  128.                     wp = HEAD->ATO;    /* 戻る */
  129.                     break;
  130.                 }
  131.                 if (wp->MAE == NULL) {
  132.                     wp = wp->ATO;
  133.                     counter--;
  134.                     break;
  135.                 }
  136.             }
  137.         }
  138.     }
  139.     if (movel) {
  140.         *movel = counter;
  141.     }
  142.     return(wp);
  143. }
  144.  
  145. /* up の指す行の行頭に s1+s2 を挿入し、次々に送って行く。最後まで勝負する */
  146. /* エコーする */
  147. void
  148. line_arrange(UNIT *up,STR s1,STR s2)
  149. {
  150.     UBYTE seed[strlen(s1)+strlen(s2)+VERY_LONG_LINE+1];
  151.     UBYTE w0[VERY_LONG_LINE],retw[VERY_LONG_LINE];
  152.     UNIT *wp,*np;
  153.     register int restl;
  154.     int flag;
  155.  
  156.     strcpy(seed,s1);
  157.     strcat(seed,s2);    /* まずは挿入部分 */
  158. #if 0    
  159.     if (!(restl = strlen(seed))) {    /* 空なら終わり */
  160.         return;
  161.     }
  162. #endif
  163.     if (up == NIL) {
  164.         error("バグが発生しました");
  165.         return;
  166. /*        ctrl_x_ctrl_c();*/
  167.     }
  168.  
  169.     line_make_bag_list(seed);
  170. /*printf("seed = %s",seed);binkey();*/
  171.  
  172.     while(1) {
  173.         wp = line_get_from_bag();
  174.         if (BAG_HEAD == NIL) {    /* 最後の行なら抜ける */
  175.             break;
  176.         }
  177.         line_insert1_mae_echo(wp,up);    /* 1行挿入 */
  178.     }
  179.  
  180.     if ((up == TAIL) && wp) {
  181.         line_insert1_mae_echo(wp,up);    /* 最後の一行を挿入して終り */
  182.         return;
  183.     }
  184.  
  185.     np = up;
  186.     line_get_body(seed,wp);    /* 最後の一行のデータを取って来る */
  187.     while(strlen(seed)) {
  188.         if (np == TAIL) {    /* 最後に達した */
  189.             wp = line_get_free_and_store(seed);
  190.             line_append1_echo(wp);
  191. /*window0();printf("1break");binkey();*/
  192.             break;
  193.         }
  194.         line_get_body(w0,np);    /* w0 は常にその次の行の中身を示す */
  195. /*window0();printf("[%s][%s]",seed,w0);binkey();*/
  196.         flag = cut_2line_link_check(seed,w0,retw,seed,CURRENT_JIZUME);
  197.         if (!flag) {        /* 出入りが無かった */
  198.             line_empty_bag((STR) NIL);
  199.             wp = line_get_free_and_store(retw);
  200.             line_insert1_mae_echo(wp,np);    /* 最後の一行を挿入して終り */
  201. /*window0();printf("2break");binkey();*/
  202.             break;
  203.         }
  204.         if (flag < 0) {                /* 前に送られた */
  205.             if (!strlen(seed) && (etc_last(retw) != CR)) {    /* 短過ぎた */
  206.                                     /* もしくはちょうど */
  207. /*window0();printf("TOO SHORT[%s][%s]",seed,retw);binkey();*/
  208.                 strcpy(seed,retw);    /* 戻す */
  209.                 /* np -> w0 ですでに追加してある! */
  210.                 np = np->ATO;
  211.                 line_delete1_echo_after_bag(np->MAE);
  212.                 if (np == TAIL) {    /* もう後はないから1行作って終わり */
  213. /*window0();printf(seed);binkey();*/
  214.                     wp = line_get_free_and_store(seed);
  215. /*                    line_delete1_echo_after_bag(TAIL->MAE);*/
  216.                     line_append1_echo(wp);
  217. /*window0();printf("3break");binkey();*/
  218.                     break;
  219.                 }
  220.                 continue;
  221. #if 0
  222.                 line_cat_body(seed,np);    /* その次の行を取って来る */
  223. window0();printf("TOO SHORT2[%s]",seed);binkey();
  224. /*                strcat(seed,w0);*/
  225.                 np = np->ATO;
  226.                 line_delete1_echo_after_bag(np->MAE);
  227.                     /* 一行削除:ただしその行は袋の後ろにあること */
  228.                 continue;
  229. #endif
  230.             } else {            /* retw で1行作って良い */
  231.                 line_store_and_echo(np,retw);
  232.                 np = np->ATO;
  233.                 continue;
  234.             }
  235.         }
  236.         if (flag > 0) {                /* 後ろに送った */
  237.                             /* retw で1行作って良い */
  238.             wp = line_get_free_and_store(retw);
  239. /*            line_store_and_echo(np,retw);*/
  240.             line_insert1_mae_echo(wp,np);    /* 挿入する */
  241.             np = np->ATO;
  242. /*window0();printf(seed);binkey();*/
  243.             seed[strlen(seed)-strlen(w0)] = EOS;
  244.             /* w0 は変わらず */
  245.             continue;
  246.         }
  247.     }
  248.     return;
  249. }
  250.  
  251. /* up の指す行から、次々に整行して行く。最後まで勝負する */
  252. /* エコーする */
  253. void
  254. line_arrange_all(UNIT *up)
  255. {
  256.     register UNIT *wp,*wp0,*wp1;
  257.     UBYTE w0[VERY_LONG_LINE*2],w1[VERY_LONG_LINE];
  258.  
  259.     if ((wp0 = up) == TAIL) {    /* エラーやがな */
  260.         return;
  261.     }
  262.     line_get_body(w0,wp0);
  263.     wp1 = wp0->ATO;
  264.  
  265.     while(1) {
  266.         if (wp1 != TAIL) {    /* 最後の行でないなら */
  267.             line_get_body(w1,wp1);    /* 行のデータを取って来る */
  268.             strcat(w0,w1);
  269.             wp = wp1->ATO;
  270. /*printf("[[%x:%x]]\n",wp1,wp);binkey();*/
  271.             line_set_free(wp1);    /* wp1 を捨てる */
  272.             wp1 = wp;
  273.         }
  274.         while(1) {
  275.             cut_line(w0,w1,w0,CURRENT_JIZUME);    /* カットしてみる */
  276.             if (*w0) {        /* 1行取れた */
  277.                 wp = line_get_free_and_store(w1);
  278. /*printf("(取れた%d:%d)",strlen(w1),kkk);binkey();*/
  279.                 line_insert1_mae(wp,wp0);
  280.             } else {
  281. /*printf("(取れなかった%d:%d)",strlen(w1),kkk);binkey();*/
  282.                 strcpy(w0,w1);    /* 戻す */
  283. /*window0();printf("4break");binkey();*/
  284.                 break;
  285.             }
  286.         }
  287.         if (wp1 == TAIL) {
  288.             line_store(wp0,w0);
  289.             wp0->ATO = TAIL;
  290.             TAIL->MAE = wp0;
  291. /*window0();printf("5break");binkey();*/
  292.             break;
  293.         }
  294.     }
  295. }
  296.  
  297. void
  298. line_to_bag(STR s)
  299. {
  300.     STR b;
  301.     UBYTE bag_temp_work[VERY_LONG_LINE];
  302.     int l;
  303.  
  304.     if ((BAG_LENGTH + (l = strlen(s))) > BAG_LIMIT) {
  305.         line_arrange(SCREEN[CWY1]->ATO,s,BAG);
  306.         line_empty_bag((STR) NIL);    /* 袋を空にする */
  307.     } else {
  308.         strcpy(BAG0,s);
  309.         strcat(BAG0,BAG);
  310.         b = BAG;
  311.         BAG = BAG0;
  312.         BAG0 = b;
  313.         BAG_LENGTH += l;
  314.     }
  315. }
  316.  
  317. void
  318. line_seigyou()
  319. {
  320.     if (SCREEN[CWY1] && BAG_LENGTH) {
  321.         under_print((STR) "整行中・・・");
  322.         if (SCREEN[CWY1] == TAIL) error("6666");
  323.         if (SCREEN[CWY1]->ATO == NIL) error("7777");
  324.         line_arrange(SCREEN[CWY1]->ATO,(UBYTE *)"\0",BAG);/* ,,, */
  325.         line_empty_bag((STR) NIL);    /* 袋を空にする */
  326.         under_blanc();
  327.     }
  328. }
  329.  
  330. /* s に袋の中身を転送し、袋を空にする */
  331. /* s が NIL なら転送しない */
  332. void
  333. line_empty_bag(STR s)
  334. {
  335.     if (!BAG_LENGTH) {    /* 袋は空である */
  336.         if (s) {
  337.             *s = EOS;
  338.         }
  339.     } else {        /* 袋は空ではない */
  340.         if (s) {
  341.             strcpy(s,BAG);
  342.         }
  343.     }
  344.     *BAG_CONTENT0 = *BAG_CONTENT1 = EOS;
  345.     BAG = BAG_CONTENT0;
  346.     BAG0 = BAG_CONTENT1;
  347.  
  348.     while(BAG_HEAD) {
  349.         UNIT *p;
  350.  
  351.         p = BAG_HEAD->ATO;
  352.         line_set_free(BAG_HEAD);
  353.         BAG_HEAD = p;
  354.     }
  355.     BAG_LENGTH = 0;            /* 袋の初期化 */
  356.     BAG_HEAD = BAG_TAIL = NIL;    /* bag の頭、尻尾へのポインタを無効化 */
  357. }
  358.  
  359. /* 一行削除:ただしその行は袋の後ろにあること */
  360. /* エコーしない */
  361. void
  362. line_delete1(UNIT *up)
  363. {
  364.     line_deleten(up->MAE,up->ATO);    /* 二つの行の間を削除する */
  365. }
  366.  
  367. /* 一行削除:ただしその行は袋の後ろにあるか、もしくは整行済みであること */
  368. /* エコーする */
  369. void
  370. line_delete1_echo_after_bag(UNIT *up)
  371. {
  372.     line_deleten_echo(up->MAE,up->ATO);    /* 二つの行の間を削除する */
  373. }
  374.  
  375. void
  376. line_connect(UNIT *maep,UNIT *atop)
  377. {
  378.     maep->ATO = atop;    /* 前の行の後ろを、後ろの行にする */
  379.     atop->MAE = maep;    /* 後ろの行の前を、前の行にする */
  380. }
  381.  
  382. /* maep < 削除される < atop */
  383. /* 与えられた行は削除されない */
  384. void
  385. line_deleten_echo(UNIT *maep,UNIT *atop)
  386. {
  387.     UNIT *wp_mae,*wp_ato,*wp,*wp0;
  388.  
  389.     wp_mae = maep;
  390.     wp_ato = atop;
  391.     wp = wp_mae->ATO;
  392.  
  393.     /* atop を wp_mae に手繰る */
  394.     while((wp_mae = wp) != atop) {
  395.         if (wp_ato) {                /* 尾に当たれば自動的に止まる */
  396.             disp_replace(wp_mae,wp0 = wp_ato);    /* 前を後で置き換える */
  397.             wp = wp_mae->ATO;
  398.             wp_ato = wp_ato->ATO;
  399.             line_set_free_with_ext(wp_mae);
  400.         } else {
  401. /*            disp_replace(wp_mae,wp0 = wp_ato);    前を後で置き換える */
  402.             break;
  403.         }
  404.     }
  405.     if (wp_ato) {
  406.         disp_replace_after(wp0,wp0->ATO);
  407.     }
  408.     line_connect(maep,atop);            /* 二つの行を接続する */
  409. }
  410.  
  411. #if 1
  412. /* SCREEN[] から maep < 削除される < atop */
  413. /* 与えられた行は削除されない */
  414. void
  415. line_deleten_SCREEN(UNIT *maep,UNIT *atop)
  416. {
  417.     UNIT *wp_mae,*wp_ato,*wp,*wp0;
  418.     UBYTE string[VERY_LONG_LINE];
  419.  
  420.     line_connect(maep,atop);            /* 二つの行を接続する */
  421.     return;
  422.  
  423.     wp_mae = maep;
  424.     wp_ato = atop;
  425.     wp = wp_mae->ATO;
  426.  
  427.     /* atop を wp_mae に手繰る */
  428.     while((wp_mae = wp) != atop) {    /* atop は削除されないから、そこに達したら終了 */
  429.         if (wp_ato) {        /* 尾に当たれば自動的に止まる */
  430.             disp_replace_SCREEN(wp_mae,wp0 = wp_ato);    /* 前を後で置き換える */
  431.             wp = wp_mae->ATO;
  432.             wp_ato = wp_ato->ATO;
  433.             line_set_free_with_ext(wp_mae);
  434.         } else {
  435. /*            disp_replace_SCREEN(wp_mae,wp0 = wp_ato);    前を後で置き換える */
  436.             break;
  437.         }
  438.     }
  439.     if (wp_ato) {
  440.         disp_replace_after_SCREEN(wp0,wp0->ATO);
  441.     }
  442. /*    disp_replace_after(atop->MAE,atop);*/
  443. /*    line_set_free_with_ext(atop->MAE);*/
  444.     line_connect(maep,atop);            /* 二つの行を接続する */
  445. }
  446. #endif
  447.  
  448. /* maep < 削除される < atop */
  449. /* 与えられた行は削除されない */
  450. /* エコーしない */
  451. void
  452. line_deleten(UNIT *maep,UNIT *atop)
  453. {
  454.     register UNIT *wp_mae,*wp;
  455.  
  456.     wp_mae = maep->ATO;
  457. /*printf("[%x:%x]",maep,atop);binkey();*/
  458.     do {
  459.         wp = wp_mae->ATO;
  460.         line_set_free_with_ext(wp_mae);
  461.     } while((wp_mae = wp) != atop);
  462.  
  463.     line_connect(maep,atop);            /* 二つの行を接続する */
  464. }
  465.  
  466. /* seed をカッティングして袋のリストにする */
  467. void
  468. line_make_bag_list(STR seed)
  469. {
  470.     UBYTE s[VERY_LONG_LINE],l[VERY_LONG_LINE],w[VERY_LONG_LINE];
  471.     UNIT *p;
  472.     UINT c,jizume;
  473.     FILE *fp;
  474.  
  475.     *s = EOS;                /* 前からの繰り越しはなし */
  476.     jizume = CURRENT_JIZUME;
  477.     do {
  478.         if (!*s) {    /* s がヌルなら適当な長さだけ読み出す */
  479.             strncpy(s,seed,jizume + 4);
  480.             s[jizume + 4] = EOS;
  481.             seed += strlen(s);
  482.         }
  483.         while(1) {
  484.             if (string_disp_len(s) > (jizume+4)) {    /* 禁則はみだしがあるので長め */
  485.                 break;
  486.             }
  487.             strncpy(l,seed,jizume + 4);
  488.             l[jizume + 4] = EOS;
  489.             seed += strlen(l);    /* 適当な長さだけ読み出す */
  490.             strcat(s,l);        /* 前からの繰り越しの後に加える */
  491.             if (!*seed) break;
  492.         }
  493.         if (!*s) {    /* 前部使った */
  494.             break;
  495.         }
  496.         cut_line(s,w,s,jizume);
  497.  
  498.         p = line_append_bag_list(w);
  499.         if (p == NIL) {            /* フリーラインが無い! */
  500.             etc_inp_y((STR)"メモリが足りません。中断します [Y]?");
  501.             line_empty_bag(NULL);
  502.             return;
  503.         }
  504.     } while(*seed || *s);
  505. }
  506.  
  507. UNIT *
  508. line_append_bag_list(UBYTE *s)
  509. {
  510.     UNIT *p;
  511.     
  512.     if (!(p = line_get_free_and_store(s))) return(NIL);
  513.  
  514.     if (BAG_HEAD) {            /* 袋リストがある */
  515.         BAG_TAIL->ATO = p;    /* 最後の次が手持ちになる */
  516.         p->MAE = BAG_TAIL;    /* 手持ちの前は最後 */
  517.         p->ATO = NIL;        /* 新しい最後は NIL を指す */
  518.         BAG_TAIL = p;        /* 新しい最後を指す */
  519.     } else {            /* フリーラインがない */
  520.         BAG_HEAD = BAG_TAIL = p;
  521.         p->MAE = p->ATO = NIL;
  522.     }
  523.     return(p);
  524. }
  525.  
  526. /* 袋リストの頭から順番に1つづつ外して行く */
  527. UNIT *
  528. line_get_from_bag()
  529. {
  530.     UNIT *wp;
  531.  
  532.     if (wp = BAG_HEAD) {
  533.         BAG_HEAD = BAG_HEAD->ATO;
  534.     }    /* HEAD が NIL なら TAIL は無効だからこれでいいのだ */
  535.     return(wp);
  536. }
  537.  
  538. /* 文字列にユニットの中身を追加する */
  539. /* 追加した長さを返す */
  540. int
  541. line_cat_body(STR l,UNIT *p)
  542. {
  543.     register int i;
  544.  
  545.     strcat(l,p->BODY);
  546.     i = line_length(p);
  547.     while (p = p->EXT) {
  548.         strcat(l,p->BODY);
  549.     }
  550.     return(i);
  551. }
  552.  
  553.  
  554. /* テキストの末尾に1行アペンドする */
  555. /* エコーしない */
  556. void
  557. line_append1(UNIT *unit_pointer)
  558. {
  559.     line_insert1_mae(unit_pointer,TAIL);
  560. }
  561.  
  562. /* テキストの末尾に1行アペンドする */
  563. /* エコーする */
  564. void
  565. line_append1_echo(UNIT *unit_pointer)
  566. {
  567.     line_insert1_mae_echo(unit_pointer,TAIL);
  568. }
  569.  
  570. /* text_line_pointer の後ろに1行挿入する */
  571. /* エコーする */
  572. void
  573. line_insert1_after(UNIT *insert_unit_pointer,UNIT *text_line_pointer)
  574. {
  575.     UNIT *n;
  576.  
  577.     if (text_line_pointer == TAIL) {
  578.         error("バグです。TAIL の後ろに挿入しようとした");
  579.     } else {
  580.         line_insert1_mae_echo(insert_unit_pointer,text_line_pointer->ATO);
  581.     }
  582. }
  583.  
  584. /* text_line_pointer の前に1行挿入する */
  585. /* エコーする */
  586. void
  587. line_insert1_mae_echo(UNIT *insert_unit_pointer,UNIT *text_line_pointer)/* ,,,, */
  588. {
  589.     UNIT *b;
  590.  
  591.     line_insert1_mae(insert_unit_pointer,text_line_pointer);
  592.     disp_check_1line_insert(insert_unit_pointer,text_line_pointer);
  593.             /* 必要ならば画面にエコーする */
  594. }
  595.  
  596. /* text_line_pointer の前に1行挿入する */
  597. /* エコーしない */
  598. void
  599. line_insert1_mae(UNIT *insert_unit_pointer,UNIT *text_line_pointer)
  600. {
  601.     UNIT *b;
  602.  
  603.     if (!insert_unit_pointer) {    /* メモリの限界に来ている */
  604.         etc_beep();
  605.         under_print0((STR)"メモリ不足:文章を保存して、終了して下さい [Y]? ");
  606.         etc_wait_y();
  607.         insert_unit_pointer = &AXE;
  608.     }
  609.  
  610.     if (text_line_pointer == HEAD) {
  611.         error("バグです。HEAD の前に挿入しようとした");
  612.     } else {
  613.         b = text_line_pointer->MAE;        /* 前の行へのポインタ */
  614.         text_line_pointer->MAE = b->ATO = insert_unit_pointer;
  615.         insert_unit_pointer->ATO = text_line_pointer;
  616.                             /* 後ろのリンク */
  617.         insert_unit_pointer->MAE = b;    /* 前のリンク */
  618.     }
  619. }
  620.  
  621.  
  622. /* フリーラインを新しく得て、与えられた文字列を格納する */
  623. /* 1ユニットで格納しきれない時は自動的に拡張する */
  624. UNIT *
  625. line_get_free_and_store_with_echo(STR s)
  626. {
  627.     UNIT *p,*p0,*q;
  628.     int l,lmin;
  629.  
  630.     if (p = line_get_free()) {
  631.         if (line_store_and_echo(p,s)) {
  632.             return(p);
  633.         } else {
  634.             line_set_free(p);
  635.         }
  636.     }
  637.     return(NIL);    /* 得られなかった */
  638. }
  639.  
  640. /* フリーラインを新しく得て、与えられた文字列を格納する */
  641. /* 1ユニットで格納しきれない時は自動的に拡張する */
  642. UNIT *
  643. line_get_free_and_store(STR s)
  644. {
  645.     UNIT *p,*p0,*q;
  646.     int l,lmin;
  647.  
  648.     if (p = line_get_free()) {
  649.         if (line_store(p,s)) {
  650.             return(p);
  651.         } else {
  652.             line_set_free(p);
  653.         }
  654.     } else {
  655.         return(NIL);    /* 1行も得られなかった */
  656.     }
  657. }
  658.  
  659. UNIT *
  660. line_get_free_and_store_ck(STR s)
  661. {
  662.     register UNIT *p;
  663.  
  664.     if (!(p = line_get_free_and_store(s))) {
  665.         error("おそらくメモリ不足です。新しい行を確保出来ません");
  666.     }
  667.     return(p);
  668. }
  669.  
  670. /* 指定されたユニット(拡張可)に与えられた文字列を格納する */
  671. /* 格納しきれない時は自動的に拡張する、余った場合も自動的に開放する */
  672. /* 画面にエコーする */
  673. UNIT *
  674. line_store_and_echo(UNIT *up, STR s)
  675. {
  676.     UNIT *wp;
  677.  
  678.     if (up == TAIL) {
  679.         wp = line_get_free_and_store(s);
  680.         line_append1_echo(wp);
  681.     } else {
  682.         line_store(up,s);
  683.         disp_check_1line_echo(up);
  684.     }
  685. }
  686.  
  687.  
  688. /* 指定されたユニット(拡張可)に与えられた文字列を格納する */
  689. /* 格納しきれない時は自動的に拡張する、余った場合も自動的に開放する */
  690. /* エコーしない */
  691. UNIT *
  692. line_store(UNIT *up, STR s)
  693. {
  694.     UNIT *p,*q;
  695.     int l,lmin;
  696.  
  697.     up->LENGTH = l = strlen(s);
  698.     if (l < BODYSIZE-1) {
  699.         strcpy(up->BODY,s);
  700.         if (up->EXT) {
  701.             line_set_free_with_ext(up->EXT);
  702.             up->EXT = NIL;
  703.         }
  704.         return(up);
  705.     }
  706.  
  707.     strncpy(up->BODY,s,lmin = BODYSIZE-1);        /* 最初のユニット */
  708.     s += lmin;
  709.     p = up;
  710.  
  711.     while ((l -= lmin) > 0) {        /* long line */
  712.         p->BODY[BODYSIZE-1] = EOS;    /* EOS を追加 */
  713.         if (!(q = p->EXT)) {        /* 拡張が必要なのに今は持ってない */
  714.             if (q = line_get_free()) {    /* 取れた */
  715.                 p->EXT = q;
  716.             } else {        /* 取れなかった */
  717.                 line_set_free_with_ext(up->EXT);
  718.                 return(NIL);
  719.             }
  720.         }
  721.         lmin = min(BODYSIZE-1,l);
  722.         strncpy(q->BODY,s,lmin);
  723.         (q->BODY)[lmin] = EOS;
  724.         s += lmin;
  725.         p = q;
  726.     }
  727.     if (p->EXT) {
  728.         line_set_free_with_ext(p->EXT);
  729.         p->EXT = NIL;
  730.     }
  731.     return(up);
  732. }
  733.  
  734. void
  735. line_get_body(STR s,UNIT *p)
  736. {
  737.     if (p) {
  738.         strcpy(s,p->BODY);
  739.         while (p = p->EXT) {
  740.             strcat(s,p->BODY);
  741.         }
  742.     }
  743. }
  744.  
  745. /* エラーなら 0 を返す */
  746. int
  747. line_make_line(int number_of_line)
  748. {
  749.     int i;
  750.     UNIT    *ptr;
  751.  
  752.     if (number_of_line) {
  753.         if (ptr = line_get_memory(number_of_line)) {
  754.                     /* フリーラインに追加していく */
  755.             for(i = 0;i < number_of_line;i++) {
  756.                 line_set_free(ptr++);
  757.             }
  758.         } else {
  759.             return(FALSE);    /* 必要な領域を確保できなかった */
  760.         }
  761.     }
  762.     return(TRUE);
  763. }
  764.  
  765. /* メモリの確保 */
  766. UNIT *
  767. line_get_memory(int number_of_line)
  768. {
  769.     int s;
  770.  
  771.     s = number_of_line*sizeof(UNIT);
  772.     if (s % 1024) {
  773.         s = s/1024+1;
  774.     } else {
  775.         s = s/1024;
  776.     }
  777.     bldmem(s);
  778.     return((UNIT *)calloc(number_of_line,sizeof(UNIT)));
  779.             /* calloc は0で初期化する */
  780. }
  781.  
  782. /* フリーなユニットへのポインタを返す */
  783. /* フリーリストから外す */
  784. /* 頭から外していく */
  785. /* ない場合は NIL を返す */
  786. UNIT *
  787. line_get_free()
  788. {
  789.     UNIT *p;
  790.  
  791. /*
  792. if (sysflag) {
  793.     int *BUS = 0;
  794.  
  795.     error("###");
  796.     *BUS = 0;
  797.     return;
  798. }
  799. sysflag = 1;
  800. */
  801.     if (LINE_SHORT) {
  802.         return(&AXE);
  803.     }
  804.     /* フリーラインがない */    /* 作れない */
  805.     if ((!FREE_LINE_COUNTER) && (!line_make_line(128))) {
  806.         LINE_SHORT = 1;
  807.         under_print0((STR)"重大な事態。メモリ不足:大事な文章を保存して、終了して下さい [Y]? ");
  808.         etc_wait_y();
  809.         return(&AXE);
  810. /*        return(NIL);*/
  811.     }
  812.  
  813.     FREE_LINE_COUNTER--;        /* フリーラインがある */
  814.     p = FREE_HEAD;
  815.     if (FREE_HEAD = FREE_HEAD->ATO) {    /* 次がある(最後ではなかった) */
  816.         FREE_HEAD->MAE = NIL;    /* 新しい先頭行の前は NIL */
  817.     } else {                /* 最後の行だった */
  818.         FREE_TAIL = NIL;        /* 尻尾に NIL を指させる */
  819.     }
  820.  
  821.     p->MAE = NIL;
  822.     p->ATO = NIL;
  823.     p->EXT = NIL;
  824.     p->LENGTH = 0;
  825.     p->BODY[0] = EOS;
  826.     return(p);
  827. }
  828.  
  829. /* フリーなユニットにする */
  830. void
  831. line_set_free(UNIT *unit_pointer)
  832. {
  833.     if (FREE_LINE_COUNTER) {            /* フリーラインがある */
  834.         FREE_TAIL->ATO = unit_pointer;        /* 最後の次が手持ち */
  835.         unit_pointer->MAE = FREE_TAIL;    /* 手持ちの前は最後 */
  836.         unit_pointer->ATO = NIL;        /* 新しい最後は NIL を指す */
  837.         unit_pointer->EXT = NIL;
  838.         FREE_TAIL = unit_pointer;        /* 新しい最後を指す */
  839.     } else {                    /* フリーラインがない */
  840.         FREE_HEAD = FREE_TAIL = unit_pointer;
  841.         unit_pointer->MAE = unit_pointer->ATO = NIL;
  842.     }
  843.  
  844.     FREE_LINE_COUNTER++;
  845. }
  846.  
  847. /* 拡張を含めて開放する */
  848. /* 再帰を使ってランララン */
  849. void
  850. line_set_free_with_ext(UNIT *unit_pointer)
  851. {
  852.     UNIT *xp;
  853.  
  854.     if (xp = unit_pointer->EXT) {
  855.         line_set_free_with_ext(xp);
  856.     }
  857.     line_set_free(unit_pointer);
  858. }
  859.  
  860. /* 現在行の n 文字目の文字コードを1バイト取って来る */
  861. UBYTE
  862. line_cl_1byte(int n)
  863. {
  864.     return(*(line_skip_xcode(CL_DATA + ANALYZE[n].BPOS)));
  865. }
  866.  
  867. /* 現在行の n 文字目の文字コードを1文字取って来る */
  868. UINT c;
  869. line_cl_code(int n)
  870. {
  871.     register STR p;
  872.     register UINT c;
  873.  
  874.     p = line_skip_xcode(CL_DATA + ANALYZE[n].BPOS);
  875.     if (iskanji(c = *p++)) {
  876.         c = (c<<8) | *p;
  877.     }
  878.     return(c);
  879. }
  880.  
  881. /* カーソルの下の文字コードを1バイト取って来る */
  882. UBYTE
  883. line_cpx_1byte()
  884. {
  885.     return(*(line_skip_xcode(CL_DATA + ANALYZE[CPX].BPOS)));
  886. }
  887.  
  888. /* カーソルの下の文字コードを取って来る */
  889. UINT
  890. line_cpx_code()
  891. {
  892.     register STR wp;
  893.     UINT c;
  894.  
  895.     wp = line_skip_xcode(&CL_DATA[ANALYZE[CPX].BPOS]);    /* 実体のアドレスを得る */
  896.     if (etc_char_byte_haba(wp) <= 1) {
  897.         return(*wp);
  898.     } else {
  899.         c = *wp++;
  900.         return(c << 8 | *wp);
  901.     }
  902. }
  903.  
  904. /* 拡張コードをスキップする */
  905. /* ポインタを返す */
  906. STR
  907. line_skip_xcode(STR p)
  908. {
  909.     register UINT c1;
  910.  
  911.     while(*p == XCODE_UP) {
  912.         c1 = *++p;
  913.         p++;
  914.         /* c1 を見て、ルビならさらに進める */
  915.         if ((XCODE_RB10 <= c1) && (c1 <= XCODE_RB2)) {    /* ルビだ */
  916.             p += 2;
  917.             if (c1 == XCODE_RB2) {
  918.                 p += 2;
  919.             }
  920.         }
  921.     }
  922.     return(p);
  923. }
  924.  
  925. /* マークコードをスキップする */
  926. /* ポインタを返す */
  927. STR
  928. line_skip_mark(STR p)
  929. {
  930.     register UINT c1;
  931.  
  932.     while(*p == XCODE_UP) {
  933.         if ((XCODE_SYSMARK <= p[1]) && (p[1] <=    XCODE_MARKLAST)) {    /* マークだ */
  934.             p += 2;
  935.         } else {
  936.             return(p);
  937.         }
  938.     }
  939. }
  940.  
  941. #if 0
  942. /* 文字列の最初の1文字が占めるバイト数を返す(拡張コードも含めたバイト数) */
  943. UINT
  944. line_cxp_char_byte(STR p)
  945. {
  946.     register int i = 0;
  947.  
  948.     while(p[i] == XCODE_UP) {
  949.         i += 2;
  950.     }
  951.     return(i + etc_char_byte_haba(p));
  952. }
  953. #endif
  954.  
  955. /* CL_DATA[bc] から始めて、次の文字までのバイト数を返す */
  956. /* *xc から表示しているとして、*xc を更新する */
  957. int
  958. line_touch_next_char(int bc,int *xc)
  959. {
  960.     return(line_touch_next_char_x(CL_DATA,bc,xc));
  961. }
  962.  
  963. /* p[bc] から始めて、次の文字までのバイト数を返す */
  964. /* *xc から表示しているとして、*xc を更新する */
  965. /* 実体を越える */
  966. int
  967. line_touch_next_char_x(STR p,int bc,int *xc)
  968. {
  969.     register UBYTE c;
  970.     register UWORD w;
  971.  
  972.     if ((c = p[bc]) < (UBYTE)'\x20') {
  973.         switch(c) {
  974.         case EOS:
  975.             return(bc);
  976.         case TAB:    /* TAB 0-7 -> 8, 8-15 -> 16... */
  977.             w = *xc + TAB_LENGTH;
  978.             w -= (w % TAB_LENGTH);
  979.             *xc = min(w,CURRENT_JIZUME);
  980. /*            *xc = w - (w % TAB_LENGTH);*/
  981.             return(bc + 1);
  982.         case CR:    /* 改行 */
  983.             (*xc) += 2;
  984.             return(bc + 1);
  985.  
  986.         default:    /* 普通のコントロールコード */
  987.             (*xc) += 2;
  988.             return(bc + 1);
  989.         }
  990.     }
  991.     if (c == XCODE_UP) {    /* 拡張コード */
  992.         switch(p[bc+1]) {    /* 次の1バイトが */
  993.         case XCODE_MARK+0:
  994.         case XCODE_MARK+1:
  995.         case XCODE_MARK+2:
  996.         case XCODE_MARK+3:
  997.         case XCODE_MARK+4:
  998.         case XCODE_MARK+5:
  999.         case XCODE_MARK+6:
  1000.         case XCODE_MARK+7:
  1001.         case XCODE_MARK+8:
  1002.         case XCODE_MARK+9:    /* マーク 0x20 - 0x29 */
  1003.         case XCODE_MARK+10:
  1004.         case XCODE_MARK+11:
  1005.         case XCODE_MARK+12:
  1006.         case XCODE_MARK+13:
  1007.         case XCODE_MARK+14:
  1008.         case XCODE_MARK+15:
  1009.  
  1010.         case XCODE_SYSMARK+0:    /* システムマーク */
  1011.         case XCODE_SYSMARK+1:
  1012.         case XCODE_SYSMARK+2:
  1013.         case XCODE_SYSMARK+3:
  1014.         case XCODE_SYSMARK+4:
  1015.         case XCODE_SYSMARK+5:
  1016.         case XCODE_SYSMARK+6:
  1017.         case XCODE_SYSMARK+7:
  1018.         case XCODE_SYSMARK+8:
  1019.         case XCODE_SYSMARK+9:
  1020.         case XCODE_SYSMARK+10:
  1021.         case XCODE_SYSMARK+11:
  1022.         case XCODE_SYSMARK+12:
  1023.         case XCODE_SYSMARK+13:
  1024.         case XCODE_SYSMARK+14:
  1025.         case XCODE_SYSMARK+15:
  1026.         case XCODE_UL:        /* 下線 */
  1027.             return(line_touch_next_char_x(p,bc+2,xc));
  1028.  
  1029.         case XCODE_RB10:    /* 予約:1文字真ん中ルビ */
  1030.         case XCODE_RB1:        /* 1文字ルビ */
  1031.         case XCODE_RB1L:    /* 1文字ルビ左(全角用) */
  1032.         case XCODE_RB1R:    /* 1文字ルビ右(全角用) */
  1033.             return(line_touch_next_char_x(p,bc+4,xc));
  1034.  
  1035.         case XCODE_RB2:        /* 2文字ルビ */
  1036.             return(line_touch_next_char_x(p,bc+6,xc));
  1037.         }
  1038.     }
  1039.     if (iskanji(c)) {    /* 普通の全角 */
  1040.         (*xc) += 2;
  1041.         return(bc + 2);
  1042.     }
  1043.     if (buff_ishan2byte(c)) {
  1044.         (*xc)++;
  1045.         return(bc + 2);
  1046.     }
  1047.     (*xc)++;
  1048.     return(bc + 1);
  1049. }
  1050.  
  1051. /* */
  1052. /* void */
  1053. line_cl_cl()
  1054. {
  1055.     register UNIT *p = CL;
  1056.  
  1057.     if (p) {
  1058.         strcpy(CL_DATA,p->BODY);
  1059.         while (p = p->EXT) {
  1060.             strcat(CL_DATA,p->BODY);
  1061.         }
  1062.     }
  1063. }
  1064.  
  1065. /* s に CL_DATA から n バイトコピーする */
  1066. void
  1067. line_cl_strncpy(STR s,int n)
  1068. {
  1069.     strncpy(s,CL_DATA,n);
  1070. }
  1071.  
  1072. /* s に CL_DATA の n バイト目からのデータを追加する */
  1073. void
  1074. line_cl_strcat(STR s,int n)
  1075. {
  1076.     strcat(s,&CL_DATA[n]);
  1077. }
  1078.  
  1079. /* s に CL_DATA の n バイト目からの l バイトのデータを追加する */
  1080. void
  1081. line_cl_strncat(STR s,int n,int l)
  1082. {
  1083.     strncat(s,&CL_DATA[n],l);
  1084. }
  1085.  
  1086. /* maep <= 削除される <= atop */
  1087. /* 与えられた行は削除されない */
  1088. /* エコーしない */
  1089. void
  1090. line_deleten_list(UNIT *maep,UNIT *atop)
  1091. {
  1092.     register UNIT *wp;
  1093.  
  1094. /*window0();*/
  1095.     if (maep) {
  1096.         while(1) {
  1097.             wp = maep->ATO;
  1098. /*printf("[%x]\n",maep);binkey();*/
  1099.             line_set_free_with_ext(maep);
  1100.             if (maep == atop) {
  1101.                 break;
  1102.             }
  1103.             maep = wp;
  1104.         }
  1105.     }
  1106. }
  1107.  
  1108. int
  1109. line_length(UNIT *p)
  1110. {
  1111.     return(p->LENGTH);
  1112. }
  1113.  
  1114. /* CL_DATA の前置している属性までさかのぼる */
  1115. /* 解析済み */
  1116. int
  1117. line_remove_attribute(int bp1)
  1118. {
  1119.     register int i,j;
  1120.  
  1121.     j = i = 0;
  1122.     while(bp1 >= ANALYZE[i].BPOS) {
  1123.         j = i++;
  1124.     }
  1125.     if (bp1 == ANALYZE[i].BPOS) {
  1126.         return(bp1);
  1127.     } else {
  1128.         return(ANALYZE[j].BPOS);
  1129.     }
  1130. }
  1131.  
  1132.